package Hxw3DEngine.core.materials.shader.filters {
	
	
	import Hxw3DEngine.core.Resource.geometry.ResourceGeometry;
	import Hxw3DEngine.core.component.Transform3D;
	import Hxw3DEngine.core.lights.DirectionalLight;
	import Hxw3DEngine.core.materials.shader.utils.FcRegisterLabel;
	import Hxw3DEngine.core.materials.shader.utils.ShaderRegisterCache;
	import Hxw3DEngine.core.materials.shader.utils.ShaderRegisterElement;
	import Hxw3DEngine.proxy.Stage3DProxy;
	import Hxw3DEngine.utils.Color;
	import Hxw3DEngine.utils.Vector3DUtils;
	
	import flash.events.Event;
	import flash.geom.Vector3D;
	
	/**
	 * 平行光 filter 
	 * @author Neil
	 * 
	 */	
	public class DirectionalLightFilter extends LightFilter {
		
		private var _light 			: DirectionalLight;		// 平行灯
		private var _dirData		: Vector.<Number>;		// 方向数据
		private var _eyeData		: Vector.<Number>;		// eye
		private var _specular 		: Color;				// 高光
		private var _specularData	: Vector.<Number>;		// 高光数据
		private var _power 			: Number = 50;			// 高光强度
		
		/**
		 * 太阳光filter 
		 * @param light
		 * 
		 */		
		public function DirectionalLightFilter(light :DirectionalLight) {
			this.priority = 13;
			this._specularData 	= Vector.<Number>([1, 1, 1, 1]);
			this._eyeData 		= Vector.<Number>([0, 0, 0, 0]);
			this._dirData 		= Vector.<Number>([0, 0, 0, 0]);
			this.light			= light;
		}
		
		public function set light(light : DirectionalLight) : void {
			if (!light) {
				return;
			}
			if (this._light) {
				this._light.removeEventListener(Event.CHANGE, change);
				this._light.transform.removeEventListener(Transform3D.UPDATE_TRANSFORM_EVENT, change);
			}
			this._light = light;
			this._light.addEventListener(Event.CHANGE, change);
			this._light.transform.addEventListener(Transform3D.UPDATE_TRANSFORM_EVENT, change);
			this.change(null);
		}
		
		/**
		 * 灯光方向改变 
		 * @param event
		 * 
		 */		
		private function change(event:Event) : void {
			this._light.transform.getDir(false, Vector3DUtils.vec0);
			this.dirData 		= Vector3DUtils.vec0;
			this.lightColor 	= this._light.color;
			this.power 			= this._light.power;
			this.ambient 		= this._light.ambient;
			this.specular 		= this._light.specular;
			this.intensity		= this._light.intensity;
		}
		
		/**
		 * 高光强度
		 * @param value
		 *
		 */
		public function set power(value : Number) : void {
			this._power = value;
			this._specularData[3] = value;
		}
		
		public function get power() : Number {
			return _power;
		}
		
		/**
		 * 高光 
		 * @return 
		 * 
		 */		
		public function get specular() : Color {
			return _specular;
		}
		
		/**
		 * 高光颜色
		 * @param value
		 * 
		 */		
		public function set specular(value : Color) : void {
			this._specular = value;
			this._specularData[0] = value.r;
			this._specularData[1] = value.g;
			this._specularData[2] = value.b;
		}
		
		/**
		 * 视角位置 
		 * @param pos
		 * 
		 */		
		private function set eyeData(pos : Vector3D):void {
			this._eyeData[0] = pos.x;
			this._eyeData[1] = pos.y;
			this._eyeData[2] = pos.z;
		}
		
		/**
		 * 灯光方向 
		 * @param dir
		 * 
		 */		
		private function set dirData(dir : Vector3D):void {
			dir.normalize();
			this._dirData[0] = -dir.x;
			this._dirData[1] = -dir.y;
			this._dirData[2] = -dir.z;
			this._dirData[3] = 0;
		}
		
		override public function update():void {
			super.update();
			this.eyeData = Stage3DProxy.cameraPos;
		}
		
		override public function getFragmentCode(regCache : ShaderRegisterCache):String {
			super.getFragmentCode(regCache);
			var eyeFc    : ShaderRegisterElement = regCache.getFc(1, new FcRegisterLabel(_eyeData),"");
			var specuFc  : ShaderRegisterElement = regCache.getFc(1, new FcRegisterLabel(_specularData),"");
			var lightDir : ShaderRegisterElement = regCache.getFc(1, new FcRegisterLabel(_dirData),"");
			var colorFc  : ShaderRegisterElement = regCache.getFc(1, new FcRegisterLabel(_lightData),"");
			var ambFc    : ShaderRegisterElement = regCache.getFc(1, new FcRegisterLabel(_ambientData),"");
						
			var ft0 : ShaderRegisterElement = regCache.getFt("法线");
			var ft1 : ShaderRegisterElement = regCache.getFt("");	
			var ft2 : ShaderRegisterElement = regCache.getFt("");
			
			//法线ft0
			mov(ft0.xyz,regCache.normalFt.xyz);
			sub(ft1.xyz,eyeFc.xyz,regCache.getV(ResourceGeometry.POSITION));
			//camer 法线ft1
			nrm(ft1.xyz,ft1.xyz);
			//高光颜色ft2
			add(ft2.xyz,lightDir.xyz,ft1.xyz);
			nrm(ft2.xyz,ft2.xyz);
			dp3(ft2.w,ft0.xyz,ft2.xyz);
			max(ft2.w,ft2.w,regCache.fc0123.x);
			pow(ft2.w,ft2.w,specuFc.w);
			//灯光颜色ft0.xyz
			dp3(ft0.w,ft0.xyz,lightDir.xyz);
			max(ft0.w,ft0.w,regCache.fc0123.x);
			mul(ft0.xyz,colorFc.xyz,ft0.w);
			// 灯光颜色=灯光颜色+环境色
			add(ft0.xyz,ft0.xyz,ambFc.xyz);
			mul(ft0.xyz,ft0.xyz,regCache.oc.xyz);
			// 高光颜色*高光
			mul(ft2.xyz,ft2.w,specuFc.xyz);
			add(ft0.xyz,ft0.xyz,ft2.xyz);
			// 高光颜色*高光
			mul(ft2.xyz,ft2.w,specuFc.xyz);
			add(ft0.xyz,ft0.xyz,ft2.xyz);
			// 强度
			mov(regCache.oc.xyz,ft0.xyz);			
			
			regCache.removeFt(ft0);
			regCache.removeFt(ft1);
			regCache.removeFt(ft2);
			
			return code;
		}
		
	}
}
